import { FormProps } from '@rjsf/core';
import { UiSchema, ValidatorType, type RJSFSchema } from '@rjsf/utils';
import defaultValidator from '@rjsf/validator-ajv8';

import {
  AmcaxForm,
  AntDesignTheme,
  CommandDialog,
  CommandDialogPlacement,
  KEYBOARD_KEY,
} from '@amcax/base';
import { defaultsDeep } from 'lodash';
import './index.scss';
import './common.scss';
import styled from 'styled-components';
import { CommandFormAutoFocus, CommandFormAutoFocusProps } from './auto-focus';
import { CommandFormFooter } from './footer';
import { ConfigProvider } from 'antd';
import { ReactNode, useEffect, useRef, useState } from 'react';
import cx from 'classnames';

export const NonDialogCommandForm = ({
  extraUiSchema,
  description,
  submitText = '确认',
  onSubmit,
  onPreview,
  onCancel,
  showCancel = true,
  showSubmit = true,
  submitLoading = false,
  previewLoading = false,
  disabled,
  isFormDataValid = true,
  ...rest
}: NonDialogCommandFormProps) => {
  const uiSchema: UiSchema = defaultsDeep(
    { ...extraUiSchema },
    {
      'ui:options': {
        description,
        classNames: 'command-form',
        submitButtonOptions: {
          norender: true,
        },
      },
    },
  );

  // 如果preview响应很快，那么ui上就不会看到一闪而过的loading，响应超过200ms才会看到loading
  // 但是ui上看不到loading时，也还是会正常阻止onPreview触发
  const uiPreviewLoadingTimer = useRef<NodeJS.Timeout>();
  // 逻辑上是否loading
  const previewLoadingRef = useRef(previewLoading);
  const [uiPreviewLoading, setUiPreviewLoading] = useState(false);

  useEffect(() => {
    if (previewLoading) {
      previewLoadingRef.current = true;
      uiPreviewLoadingTimer.current = setTimeout(() => {
        setUiPreviewLoading(true);
      }, 200);
    } else {
      previewLoadingRef.current = false;
      clearTimeout(uiPreviewLoadingTimer.current);
      uiPreviewLoadingTimer.current = null;
      setUiPreviewLoading(false);
    }
  }, [previewLoading]);

  return (
    <CommandFormAutoFocus>
      <div
        onKeyDownCapture={(e) => {
          const isFocusingInput =
            (e.target as HTMLElement).tagName === 'INPUT' ||
            (
              e.target as HTMLElement
            )?.parentElement?.parentElement?.classList.contains(
              'input-with-format',
            );
          if (e.key === KEYBOARD_KEY.ENTER && !isFocusingInput) {
            e.preventDefault();
            e.stopPropagation();
          }
        }}
      >
        <AmcaxForm
          validator={defaultValidator}
          noValidate
          {...rest}
          className={cx('rjsf', rest.className)}
          disabled={disabled ?? submitLoading}
          uiSchema={uiSchema}
          onSubmit={({ formData }) => onSubmit?.(formData)}
        >
          {rest.children ?? (
            <CommandFormFooter
              showCancel={showCancel}
              showPreview={onPreview != null}
              showSubmit={showSubmit}
              onClose={onCancel}
              onPreview={() => {
                if (previewLoadingRef.current) {
                  return;
                }
                onPreview?.();
              }}
              isPreviewLoading={uiPreviewLoading}
              isSubmitLoading={submitLoading}
              isPreviewDisabled={!isFormDataValid}
              isSubmitDisabled={!isFormDataValid}
              submitText={submitText}
            />
          )}
        </AmcaxForm>
      </div>
    </CommandFormAutoFocus>
  );
};

export type NonDialogCommandFormProps = Omit<
  FormProps<any, RJSFSchema, any>,
  'uiSchema' | 'validator' | 'onSubmit'
> & {
  extraUiSchema?: UiSchema;
  validator?: ValidatorType;
  description?: string;
  submitText?: string;
  formData?: any;
  onSubmit?: (formData: any) => void;
  onCancel?: VoidFunction;
  onPreview?: () => void;
  showCancel?: boolean;
  showSubmit?: boolean;
  submitLoading?: boolean;
  previewLoading?: boolean;
  isFormDataValid?: boolean;
};

export type CommandDialogProps = {
  title: string;
  onClose?: () => void;
  placement?: CommandDialogPlacement;
  actions?: Array<ReactNode>;
};

export type CommandFormProps = NonDialogCommandFormProps & CommandDialogProps;

const CommandForm = ({
  title,
  onClose,
  placement,
  ...rest
}: CommandFormProps) => {
  return (
    <CommandDialog
      title={title}
      onClose={onClose}
      placement={placement ?? 'topLeft'}
    >
      <NonDialogCommandForm
        {...rest}
        onCancel={onClose}
      />
    </CommandDialog>
  );
};

export default CommandForm;

// 非RJSF使用
const WrapperStyle = styled.div`
  row-gap: 8px;
  width: 300px;
  padding: 20px;
  padding-bottom: 8px;
  display: flex;
  flex-direction: column;

  .form-dialog_footer {
    width: 100%;
    padding: 8px 0 12px !important;
  }

  .pick-input_base-select {
    width: 100%;
  }
`;

export const CommandFormWrapper = ({
  children,
  ...rest
}: CommandFormAutoFocusProps) => {
  return (
    <WrapperStyle>
      <ConfigProvider theme={AntDesignTheme}>
        <CommandFormAutoFocus {...rest}>{children}</CommandFormAutoFocus>
      </ConfigProvider>
    </WrapperStyle>
  );
};
